import WebSocket from 'ws';
import QRCode from 'qrcode';
import { Buffer } from 'buffer';
import common from '../../../lib/common/common.js'
import axios from 'axios';
import Config from '../components/Config.js';
import { channel } from 'diagnostics_channel';
import Jimp from 'jimp';
import zlib from 'zlib'
import jsQR from 'jsqr';
import { promises as fs } from 'fs'
import yaml from 'yaml'
import path from 'path'
let alias = 1
async function start(serverUrl, alias, name) {
    if (dg_lab_play_plugin.connections == {})
        alias = 1
    let connection
    connection = new Connection(serverUrl)
    dg_lab_play_plugin.connections[alias] = connection;
    dg_lab_play_plugin.connections[alias].name = name
    return true
}
export class operate extends plugin {
    constructor(e = {}) {
        super({
            name: '[DG插件]控制面板',
            event: 'message',
            rule: [
                {
                    reg: /^#?(dg|郊狼)(打开|添加|增加|启动)(ws)?(连|莲|链)接/i,
                    fnc: 'add'
                },
                {
                    reg: /^#?(dg|郊狼)(\d+)?((增加|增大|提高|提升|\+)|(减少|减小|-))?(通道)?(a|b)(强度|大小)?\s*(\d+)$/i,
                    fnc: 'Control'
                },
                {
                    reg: /^#?(dg|郊狼)(断开|关闭)(ws)?(连|莲|链)接\s*(\d+)$/i,
                    fnc: 'del'
                },
                {
                    reg: /^#?(dg|郊狼)(设备)?列表$/i,
                    fnc: 'lb'
                },
                {
                    reg: /^#?(dg|郊狼)?(\d+)?(一键起爆|一键爽飞|一键开火|一键0721|0721)\s*(\d+)?/i,
                    fnc: 'Qidong'
                },
                {
                    reg: /^#?(dg|郊狼)波形(列表|队列)$/i,
                    fnc: 'waveform_list'
                },
                {
                    reg: /^#?(dg|郊狼)查看波形\s*(.*)/i,
                    fnc: 'View_Waveform_Content'
                },
                {
                    reg: /^#?(dg|郊狼)(\d+)?设置(通道)?(a|b|ab)?波形\s*([^\s]+|\d+)(?:\s*([^\s]+|\d+))?\s*(?:时间(\d+))?(?:\s*(?:时间(\d+)))?/i,
                    fnc: 'Set_Waveform'
                },
                {
                    reg: /^#?(dg|郊狼)(导入|解析)波形/,
                    fnc: 'Add_Waveform'
                },
                {
                    reg: /^#?(dg|郊狼)设置调戏数据/,
                    fnc: 'SettingMolest'
                },
                {
                    reg: /^#?(dg|郊狼)调戏群友/,
                    fnc: 'Molest'
                }
            ]
        });
        this.e = e;
    }
    /**
     * 设置调戏参数
     */
    async SettingMolest(e) {
        // 尝试从命令中直接提取参数（格式：#dg设置调戏数据 15,15,30,30）
        const directMatch = e.msg.match(/^#dg设置调戏数据\s+(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)$/i);
        
        if (directMatch) {
            // 直接处理带参数的设置命令
            const [, wavea, waveb, timea, timeb] = directMatch.map(Number);
            return await this.saveMolestConfig(e, wavea, waveb, timea, timeb);
        }
    }

    /**
     * 执行调戏
     */
    async Molest(e) {
        try {
            // 读取配置文件
            const configPath = path.join('./plugins/dg-lab-play-plugin/config/config', 'molest.yaml');
            let config;
            
            try {
                const content = await fs.readFile(configPath, { encoding: 'utf-8' });
                config = yaml.parse(content);
            } catch (err) {
                if (err.code === 'ENOENT') {
                    await e.reply('未找到调戏配置，请先使用【#dg设置调戏数据 A通道波形ID,B通道波形ID,A通道持续时间,B通道持续时间】进行配置\n注意：请使用英文逗号进行分隔\n示例：#dg设置调戏数据 15,15,30,30');
                    return true;
                }
                throw err;
            }

            // 验证配置
            if (!config || config.wavea === undefined || config.waveb === undefined || 
                config.timea === undefined || config.timeb === undefined) {
                await e.reply('调戏配置不完整，请先使用#dg设置调戏数据进行配置');
                return true;
            }

            // 生成并发送DG-Lab控制指令
            const dgCommand = `#dg设置波形 ${config.wavea} ${config.waveb} 时间${config.timea} 时间${config.timeb}`;
            this.e.msg = dgCommand;
            return await this.Set_Waveform(this.e);
            
        } catch (err) {
            await e.reply(`调戏失败: ${err.message}`);
            logger.error('调戏执行出错:', err);
            return true;
        }
    }

    /**
     * 处理调戏配置输入
     */
    async molest_config_input(e) {
        this.finish('molest_config_input');
        
        try {
            const input = e.msg.trim();
            
            if (input === '取消') {
                await e.reply('已取消设置');
                return true;
            }

            // 验证输入格式
            const match = input.match(/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)$/);
            if (!match) {
                await e.reply([
                    '格式错误！请按以下格式发送：',
                    'A波形ID,B波形ID,A持续时间,B持续时间',
                    '示例：15,15,30,30',
                    '注意：使用英文逗号分隔四个数字'
                ].join('\n'));
                return true;
            }

            const [, wavea, waveb, timea, timeb] = match.map(Number);
            return await this.saveMolestConfig(e, wavea, waveb, timea, timeb);
            
        } catch (err) {
            await e.reply(`保存配置失败: ${err.message}`);
            logger.error('配置保存错误:', err);
        }
        return true;
    }

    /**
     * 保存调戏配置（公共方法）
     */
    async saveMolestConfig(e, wavea, waveb, timea, timeb) {
        // 参数验证
        const params = [
            { name: 'A波形ID', value: wavea },
            { name: 'B波形ID', value: waveb },
            { name: 'A持续时间', value: timea },
            { name: 'B持续时间', value: timeb }
        ];
        
        for (const param of params) {
            if (isNaN(param.value)) {
                await e.reply(`${param.name}不是有效数字`);
                return true;
            }
            if (param.value <= 0 || param.value > 100) {
                await e.reply(`${param.name}必须在1-100之间`);
                return true;
            }
        }

        // 保存配置
        const configPath = './plugins/dg-lab-play-plugin/config/config';
        const configFile = path.join(configPath, 'molest.yaml');
        const newConfig = {
            wavea,
            waveb,
            timea,
            timeb,
            lastUpdated: new Date().toISOString(),
            updatedBy: e.user_id
        };

        await fs.mkdir(configPath, { recursive: true });
        await fs.writeFile(configFile, yaml.stringify(newConfig), 'utf-8');
        
        await e.reply([
            '✅ 调戏配置已保存！',
            `A波形ID: ${wavea}`,
            `B波形ID: ${waveb}`,
            `A持续时间: ${timea}秒`,
            `B持续时间: ${timeb}秒`,
            '现在可以发送 #dg调戏群友 开始调戏'
        ].join('\n'));
        
        return true;
    }
    async Set_Waveform(e) {
        let match = e.msg.match(/#(dg|郊狼)(\d+)?设置(通道)?(a|b|ab)?波形\s*([^\s]+|\d+)(?:\s*([^\s]+|\d+))?\s*(?:时间(\d+))?(?:\s*(?:时间(\d+)))?/i);
        if (!match) {
            return e.reply('指令格式错误');
        }
        let channels = match[4] ? match[4].toLowerCase() : 'ab';
        let waveNameA = match[5];
        let waveNameB = match[6];
        let timeA = match[7] ? parseInt(match[7], 10) : 10;
        let timeB = match[8] ? parseInt(match[8], 10) : 10;
        if (channels !== 'ab') {
            return e.reply('必须同时设置A和B通道');
        }
        let Yaml = await Config.getYaml('config', 'waveform');
        if (!isNaN(waveNameA)) {
            waveNameA = Object.keys(Yaml)[parseInt(waveNameA, 10) - 1];
        }
        if (!isNaN(waveNameB)) {
            waveNameB = Object.keys(Yaml)[parseInt(waveNameB, 10) - 1];
        }
        if (!Yaml || !(waveNameA in Yaml) || !(waveNameB in Yaml)) {
            return e.reply('波形ID或名称不存在');
        }
        let waveDataA = Yaml[waveNameA];
        let hexWaveFormsA = 解析波形数据(waveDataA);
        let waveDataB = Yaml[waveNameB];
        let hexWaveFormsB = 解析波形数据(waveDataB);
        let id = match[2];
        if (!id) {
            let keys = Object.keys(dg_lab_play_plugin.connections);
            if (keys.length === 0) {
                return e.reply('没有可用的设备');
            }
            id = keys[0];
        }
        if (!dg_lab_play_plugin.connections[id]) {
            return e.reply('设备不存在');
        }
        logger.info(`A的波形：${waveNameA} 持续时间：${timeA}`);
        logger.info(`B的波形：${waveNameB} 持续时间：${timeB}`);
        if (channels.includes('a')) dg_lab_play_plugin.connections[id].发送波形消息('A', JSON.stringify(hexWaveFormsA), timeA)
        if (channels.includes('b')) dg_lab_play_plugin.connections[id].发送波形消息('B', JSON.stringify(hexWaveFormsB), timeB)
        e.reply(`波形设置成功：A -> ${waveNameA} 持续时间: ${timeA}, B -> ${waveNameB} 持续时间: ${timeB}`);
    }
    async View_Waveform_Content(e) {
        let Yaml = await Config.getYaml('config', 'waveform');
        let msg = [];
        let name = '';
        let match = e.msg.match(/^#(dg|郊狼)查看波形\s*(\d+|[\s\S]+)/i);
        if (match) {
            let query = match[2].trim();
            if (!isNaN(query)) {
                let id = parseInt(query, 10);
                if (id >= 0 && id < Object.keys(Yaml).length) {
                    let key = Object.keys(Yaml)[id];
                    let value = Yaml[key];
                    name = key;
                    msg.push(`波形ID: ${id}\n波形: ${name}\n${value.join('\n')}}`);
                }
            } else {
                if (Yaml[query]) {
                    name = query;
                    msg.push(`波形: ${name}\n${Yaml[name].join('\n')}`);
                }
            }
        }
        if (msg.length == 0) {
            return e.reply('该ID或波形名字不存在');
        }
        e.reply(common.makeForwardMsg(this.e, msg, `波形${name}内容`));
    }
    async waveform_list(e) {
        let Yaml = await Config.getYaml('config', 'waveform');
        let msg = [];
        Object.keys(Yaml).forEach((name, index) => {
            let waveformID = index + 1;
            msg.push(`波形ID: ${waveformID}\n波形: ${name}`);
        });
        await e.reply(common.makeForwardMsg(this.e, msg, '波形列表'));
        return true;
    }
    async Qidong(e) {
        let match = e.msg.match(/#(dg|郊狼)?(\d+)?(一键起爆|一键爽飞|一键开火|一键0721|0721)\s*(\d+)?/i);
        let id = match[2];
        if (!id) {
            let keys = Object.keys(dg_lab_play_plugin.connections);
            if (keys.length === 0) {
                return e.reply('没有可用的设备');
            }
            id = keys[0];
        }
        if (!dg_lab_play_plugin.connections[id]) {
            return e.reply('设备不存在');
        }
        let time = match[4] ? Number(match[4]) : 10;
        const originalA = dg_lab_play_plugin.connections[id].A;
        const originalB = dg_lab_play_plugin.connections[id].B;
        e.reply(`开始起爆！\n先前的通道A强度为${originalA}\n通道B强度为${originalB}\n\n强度分别提升到${dg_lab_play_plugin.connections[id].A_S}, ${dg_lab_play_plugin.connections[id].B_S}`);
        await dg_lab_play_plugin.connections[id].设置通道强度('A', dg_lab_play_plugin.connections[id].A_S);
        await dg_lab_play_plugin.connections[id].设置通道强度('B', dg_lab_play_plugin.connections[id].B_S);
        setTimeout(() => {
            dg_lab_play_plugin.connections[id].设置通道强度('A', originalA);
            dg_lab_play_plugin.connections[id].设置通道强度('B', originalB);
            e.reply('起爆结束...');
        }, time * 1000);
    }
    async lb(e) {
        let msg = []
        for (const i in dg_lab_play_plugin.connections)
            msg.push(`设备ID:${i}${dg_lab_play_plugin.connections[i].name == '' ? '' : `\n设备名字: ${dg_lab_play_plugin.connections[i].name}`}\n状态: ${dg_lab_play_plugin.connections[i].clientId != '' ? '已连接' : '连接已断开'}\n设备状态: ${dg_lab_play_plugin.connections[i].targetId != '' ? '设备已连接' : '设备连接已断开'}\nA通道强度大小: ${dg_lab_play_plugin.connections[i].A}\nB通道强度大小: ${dg_lab_play_plugin.connections[i].B}\nA通道强度大小上限: ${dg_lab_play_plugin.connections[i].A_S}\nB通道强度大小上限: ${dg_lab_play_plugin.connections[i].B_S}`)
        msg = await this.e.runtime.common.makeForwardMsg(this.e, msg, '设备信息详情')
        e.reply(msg)
    }
    async Control(e) {
        let isJustone = /((增加|增大|提高|提升|\+)|(减少|减小|-))/.test(e.msg);
        if (isJustone) {
            let match = e.msg.match(/^#(dg|郊狼)(\d+)?((增加|增大|提高|提升|\+)|(减少|减小|-))?(通道)?(a|b)(强度|大小)?\s*(\d+)$/i);
            if (!match) {
                return e.reply('指令解析错误');
            }
            let target = match[7].toUpperCase();
            let operation = /增加|增大|提高|提升|\+/.test(match[3]);
            let deviceId = match[2];
            if (!deviceId) {
                let keys = Object.keys(dg_lab_play_plugin.connections);
                if (keys.length === 0) {
                    return e.reply('没有可用的设备');
                }
                deviceId = keys[0];
            }
            let changeValue = Number(match[9]);
            if (!dg_lab_play_plugin.connections[deviceId]) {
                return e.reply('设备不存在');
            }
            let currentStrength = dg_lab_play_plugin.connections[deviceId][target];
            let strengthLimit = dg_lab_play_plugin.connections[deviceId][`${target}_S`];
            if (currentStrength === undefined || strengthLimit === undefined) {
                return e.reply('无法获取当前设备的强度信息');
            }
            let targetNumber = operation ? currentStrength + changeValue : currentStrength - changeValue;
            if (targetNumber < 0 || targetNumber > strengthLimit) {
                return e.reply('非法的操作：数值超限');
            }
            await dg_lab_play_plugin.connections[deviceId].设置通道强度(target, targetNumber);
            e.reply('操作完成');
        } else {
            e.reply('未检测到合法的操作指令');
        }
    }
    async del(e) {
        let id = e.msg.match(/(\d+)/);
        if (id) {
            id = id[0];
            if (dg_lab_play_plugin.connections[id]) {
                dg_lab_play_plugin.connections[id].断开连接();
                delete dg_lab_play_plugin.connections[id];
                let reorderedConnections = {};
                let maxAlias = 0;
                Object.keys(dg_lab_play_plugin.connections).sort((a, b) => a - b).forEach((key, index) => {
                    let newKey = index + 1;
                    reorderedConnections[newKey] = dg_lab_play_plugin.connections[key];
                    maxAlias = Math.max(maxAlias, newKey);
                });
                dg_lab_play_plugin.connections = reorderedConnections;
                alias = maxAlias + 1;
                return e.reply('删除完成');
            }
        }
        return e.reply('设备不存在')
    }
    async add(e) {
        let msg = e.msg;
        let url;
        let name;
        msg = msg.replace(/^#(dg|郊狼)(打开|添加|增加|启动)(ws)?(连|莲|链)接/i, '');
        name = msg == '' ? '' : msg
        url = (await Config.getYaml('config', 'config')).default_ws_address
        try {
            await start(url, String(alias), name);
        } catch (error) {
            this.reply(`连接时发生错误:\n${error.message}`);
            logger.error(error);
            return;
        }
        for (let i = 0; i < 10; i++) {
            if (dg_lab_play_plugin.connections[String(alias)].clientId)
                break
            if (i == 9)
                return e.reply('ClientId获取失败')
            await common.sleep(1000)
        }
        let Qr_url = `https://www.dungeon-lab.com/app-download.php#DGLAB-SOCKET#${url}${dg_lab_play_plugin.connections[String(alias)].clientId}`;
        let msgid;
        try {
            const buffer = await generateQRCodeBuffer(Qr_url);
            if (buffer) {
                msgid = await e.reply(['请打开DG-LAB APP点击右下角sockets扫码连接', segment.image(buffer)]);
            }
        } catch (error) {
            this.reply('生成二维码失败');
            logger.error(error);
            return;
        }
        let cs = 20;
        for (let n = 0; n < cs; n++) {
            if (dg_lab_play_plugin.connections[String(alias)].检查ID状态()) {
                e.reply('连接完成');
                e.isGroup ? e.group.recallMsg(msgid.message_id) : e.friend.recallMsg(msgid.message_id)
                let i = alias
                e.reply(`设备${i}\n状态: ${dg_lab_play_plugin.connections[i].clientId != '' ? '已连接' : '连接已断开'}\n设备状态: ${dg_lab_play_plugin.connections[i].targetId != '' ? '设备已连接' : '设备连接已断开'}\nA通道强度大小: ${dg_lab_play_plugin.connections[i].A}\nB通道强度大小: ${dg_lab_play_plugin.connections[i].B}\nA通道强度大小上限: ${dg_lab_play_plugin.connections[i].A_S}\nB通道强度大小上限: ${dg_lab_play_plugin.connections[i].B_S}`)
                break;
            }
            await common.sleep(2000);
            if (n === cs - 1) {
                e.reply('连接失败');
                e.isGroup ? e.group.recallMsg(msgid.message_id) : e.friend.recallMsg(msgid.message_id)
                dg_lab_play_plugin.connections[String(alias)].断开连接();
                delete dg_lab_play_plugin.connections[String(alias)];
                return
            }
        }
        alias++;
    }
    async Add_Waveform(e) {
        let Url = e.msg.replace(/^#?(dg|郊狼)(导入|解析)波形/i, '').trim()
        Url = Url ? [Url] : []
        if (Url.length == 0)
            Url = await 二维码解析(e)
        if (!Url) {
            await e.reply('.二维码解析失败或消息内不含链接')
            return true
        }
        let 处理结果 = await Promise.all(Url.map(async (url, index) => {
            if (url == null || url == false)
                return '此图片不含二维码或读取失败'
            const hexString = url.replace('https://www.dungeon-lab.com/app-download.php#DGLAB-PULSE#', '')
            let base64String
            try {
                base64String = await gunzip(hexString)
            } catch (error) {
                logger.error(error)
                return await this.reply('Gzip解码失败')
            }
            let waveinfo = Buffer.from(Buffer.from(base64String, 'base64').toString('utf8'), 'base64').toString('utf8')
            return {
                waveinfo,
                waveform: Anal_waveinfo(waveinfo),
                index,
            }
        }))
        处理结果.sort((a, b) => a.index - b.index)
        let msg = []
        处理结果.forEach(i => {
            if (i == '此图片不含二维码或读取失败')
                msg.push(i)
            else
                msg.push(['原始数据: \n',i.waveinfo, '\n\n','解析后的数据: \n', JSON.stringify(i.waveform)])
        })
        await e.reply(common.makeForwardMsg(e, msg))
        return true
        /** 数据增删待实现 */
    }
}
class Connection {
    constructor(serverUrl) {
        this.ws = new WebSocket(serverUrl);
        this.clientId = '';
        this.targetId = '';
        this.name = '';
        this.A = 0;
        this.B = 0;
        this.A_S = 0;
        this.B_S = 0;
        this.ws.on('open', () => {
            logger.info(`[dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} 已连接到服务器`);
        });
        this.ws.on('message', (data) => {
            let message
            try {
                message = JSON.parse(data);
            } catch {
                logger.info('收到非JSON格式消息:', data)
                return;
            }
            switch (message.type) {
                case 'bind':
                    if (!this.clientId && message.clientId) {
                        logger.info(`[dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} 绑定成功:`, message);
                        this.clientId = message.clientId;
                    }
                    if (!this.targetId && message.targetId) {
                        this.targetId = message.targetId;
                        logger.info(`[dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} targetid 绑定成功:`, message.targetId);
                    }
                    break;
                case 'msg':
                    logger.info(`[dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} 收到消息:`, message);
                    if (!this.targetId && message.targetId) {
                        this.targetId = message.targetId;
                        logger.info(`[dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} targetid 绑定成功:`, message.targetId);
                    }
                    if (/^strength/.test(message.message)) {
                        let match = message.message.match(/strength-(\d+)\+(\d+)\+(\d+)\+(\d+)/)
                        if (match) {
                            this.A = Number(match[1])
                            this.B = Number(match[2])
                            this.A_S = Number(match[3])
                            this.B_S = Number(match[4])
                        }
                    }
                    break;
                case 'heartbeat':
                    logger.info(`[dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} 心跳检测:`, message);
                    break;
                default:
                    logger.info(`[dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} 未知消息类型:`, message);
            }
        });
        this.ws.on('close', () => {
            logger.info(`[dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} 连接已关闭`);
            this.clientId = '';
            this.targetId = '';
        });
        this.ws.on('error', (error) => {
            logger.error(`[dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} WebSocket 错误:`, error);
        });
    }
    检查ID状态(id = 'targetId') {
        if (id == 'targetId')
            return this.targetId != '';
        if (id == 'clientId')
            return this.clientId != '';
    }
    发送波形消息(Target, wave, time) {
        Target = Target.toUpperCase()
        const data = {
            type: 'clientMsg',
            message: `${Target}: ${wave}`,
            clientId: this.clientId,
            targetId: this.targetId,
            time,
            channel: Target
        }
        this.发送自定义消息(data)
    }
    发送强度调节指令(type, channel, strength, message = 'set channel') {
        if (!this.clientId) {
            logger.error(`[dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} clientId 未初始化`);
            return;
        }
        switch (channel) {
            case 'A':
                channel = 1;
                break;
            case 'B':
                channel = 2;
                break;
            default:
                if (!/^(\d+)$/.test(channel))
                    throw 'channel参数非法';
                break;
        }
        const data = {
            type,
            strength,
            message,
            channel,
            clientId: this.clientId,
            targetId: this.targetId,
        };
        return this.发送自定义消息(data);
    }
    async 设置通道强度(Target, Number_) {
        let channel;
        Target = Target.toUpperCase() || Number(Target) || Target
        switch (Target) {
            case 'A':
                channel = 1;
                break;
            case 'B':
                channel = 2;
                break;
            default:
                channel = Target
        }
        const data = {
            type: 4,
            clientId: this.clientId,
            targetId: this.targetId,
            message: `strength-${channel}+2+${Number_}`
        };
        this.发送自定义消息(data)
        logger.info(`通道${Target}的强度已调整到 ${Number_}`);
        return true;
    }
    增加A通道强度() {
        if (!this.targetId) return logger.error(`[dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} 未连接设备`);
        return this.发送强度调节指令(2, 'A', 1);
    }
    减少A通道强度() {
        if (!this.targetId) return logger.error(`[dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} 未连接设备`);
        return this.发送强度调节指令(1, 'A', 1);
    }
    增加B通道强度() {
        if (!this.targetId) return logger.error(`dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} 未连接设备`);
        return this.发送强度调节指令(2, 'B', 1);
    }
    减少B通道强度() {
        if (!this.targetId) return logger.error(`[dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} 未连接设备`);
        return this.发送强度调节指令(1, 'B', 1);
    }
    清空波形队列(Target) {
        Target = Target.toUpperCase() || Number(Target) || Target
        let channel;
        switch (Target) {
            case 'A':
                channel = 1
                break;
            case 'B':
                channel = 2
                break;
            default:
                break;
        }
        let msg = `clear-${channel}`;
        const data = {
            type: 'msg',
            clientId: this.clientId,
            targetId: this.targetId,
            message: msg,
            channel: Target
        };
        return this.发送自定义消息(data);
    }
    发送自定义消息(data) {
        logger.info(`[dg-play-plugin]${this.name != '' ? `[${this.name}]` : `[${this.clientId}]`} 发送消息: ${JSON.stringify(data, null, 1)}`)
        this.ws.send(JSON.stringify(data));
    }
    断开连接() {
        this.ws.close()
    }
}
async function generateQRCodeBuffer(url) {
    try {
        // 生成二维码的 Buffer
        const qrCodeBuffer = await QRCode.toBuffer(url);
        return qrCodeBuffer;
    } catch (error) {
        console.error('生成二维码失败:', error);
    }
}
async function getPublicIp() {
    try {
        const response = await axios.get('https://api.ipify.org?format=json');
        return response.data.ip;
    } catch (error) {
        console.error('获取公网 IP 失败:', error);
        throw new Error('获取公网 IP 失败');
    }
}
function 解析波形数据(waveForms) {
    const hexWaveForms = waveForms.map(waveForm => {
        const hex1 = waveForm[0].map(value => value.toString(16).padStart(2, '0')).join('');
        const hex2 = waveForm[1].map(value => value.toString(16).padStart(2, '0')).join('');
        return hex1 + hex2;
    });
    return hexWaveForms;
}
/** gzip解压 */
async function gunzip(hexString) {
    const byteArray = Buffer.from(hexString, 'hex')

    return new Promise((resolve, reject) => {
        zlib.gunzip(byteArray, (err, buffer) => {
            if (err) {
                logger.error('Error:' + err)
                reject(err) // 如果发生错误，使用 reject 返回错误信息
            } else {
                const base64String = buffer
                logger.info('Base64 String:' + base64String)
                resolve(base64String) // 解压成功时使用 resolve 返回 base64 字符串
            }
        })
    })
}
/** 频率换算 */
function getOutputValue(x) {
    const x_to_fx = [
        { xMin: 0, xMax: 40, k: 1, b: 10 },
        { xMin: 40, xMax: 55, k: 2, b: -30 },
        { xMin: 55, xMax: 59, k: 5, b: -195 },
        { xMin: 59, xMax: 69, k: 10, b: -490 },
        { xMin: 69, xMax: 75, k: 33, b: -2099 },
        { xMin: 75, xMax: 79, k: 50, b: -3350 },
        { xMin: 79, xMax: Infinity, k: 100, b: -7300 },
    ]
    const fx_to_output = [
        { xMin: 0, xMax: 100, k: 1, b: 0 },
        { xMin: 100, xMax: 660, k: 0.2, b: 80 },
        { xMin: 660, xMax: Infinity, k: 0.1, b: 140 },
    ]
    let fx, output
    for (let i = 0; i < x_to_fx.length; i++) {
        if (x >= x_to_fx[i].xMin && x < x_to_fx[i].xMax) {
            fx = x_to_fx[i].k * x + x_to_fx[i].b
            break
        }
    }
    for (let i = 0; i < fx_to_output.length; i++) {
        if (fx >= fx_to_output[i].xMin && fx < fx_to_output[i].xMax) {
            output = fx_to_output[i].k * fx + fx_to_output[i].b
            break
        }
    }
    return output
}
/** 解析波形信息 */
function Anal_waveinfo(waveinfo) {
    /** 将波形信息转化为数组形式方便解析 */
    waveinfo = waveinfo.split('+')
    waveinfo = waveinfo.map(part => part.split(','))
    /** 波形数据 */
    const waveform = []

    /** 启用的小节 */
    const enable = [0]
    if (waveinfo[0][15] == '1') {
        enable.push(1)
    }
    if (waveinfo[0][16] == '1') {
        enable.push(2)
    }

    /** 每小节 */
    for (let i of enable) {
        /** 波形频率数据 */
        const waveform_freq = []
        /** 波形强度数据 */
        const waveform_strength = []
        /** 开始频率 */
        const start_freq = Number(waveinfo[0][i])
        /** 结束频率 */
        const end_freq = Number((waveinfo[0][i + 12] == 1) ? waveinfo[0][i] : waveinfo[0][i + 3])
        /** 持续时间, 单位: 0.1秒 */
        const duration = Math.max(waveinfo[i + 1].length, Number(waveinfo[0][i + 9]))
        /** 每100ms(按播放速度为1x) */
        for (let m = 0; m < duration; m++) {
            /** 每25ms(按实际播放速度) */
            for (let n = 0; n < (4 / waveinfo[0][19]); n++) {
                /** 开始强度 */
                const start_strength = Number((waveinfo[i + 1][Math.floor(m * waveinfo[i + 1].length / duration)]).split('-')[1])
                /** 结束强度 */
                const end_strength = Number((Math.floor(m * waveinfo[i + 1].length / duration) + 1 < waveinfo[i + 1].length) ? ((waveinfo[i + 1][Math.floor(m * waveinfo[i + 1].length / duration) + 1]).split('-')[1]) : ((waveinfo[i + 1][Math.floor(m * waveinfo[i + 1].length / duration)]).split('-')[1]))
                /** 对脉冲元内强度插值渐变 */
                waveform_strength.push(Math.round((start_strength + (end_strength - start_strength) * ((m % Math.round(duration / waveinfo[i + 1].length)) / Math.round(duration / waveinfo[i + 1].length) + n / ((4 / waveinfo[0][19]) * Math.round(duration / waveinfo[i + 1].length)))) * 5))
                /** 频率模式 */
                switch (Number(waveinfo[0][i + 12])) {
                    /** 固定 */
                    case 1:
                        waveform_freq.push(Math.round(getOutputValue(start_freq)))
                        break
                    /** 节内渐变：小节的全部持续时间内频率会逐渐从频率1渐变到频率2 */
                    case 2:
                        waveform_freq.push(Math.round(getOutputValue(start_freq + (end_freq - start_freq) * (m / duration + n / ((4 / waveinfo[0][19]) * duration)))))
                        break
                    /** 元内渐变：小节每个脉冲元的全部持续时间内频率会逐渐从频率1渐变到频率2 */
                    case 3:
                        waveform_freq.push(Math.round(getOutputValue(start_freq + (end_freq - start_freq) * ((m % Math.round(duration / waveinfo[i + 1].length)) / Math.round(duration / waveinfo[i + 1].length) + n / ((4 / waveinfo[0][19]) * Math.round(duration / waveinfo[i + 1].length))))))
                        break
                    /** 元间渐变：小节每个脉冲元内部的频率是固定的，但是第一个脉冲元到最后一个脉冲元的频率会从频率1渐变到频率2 */
                    case 4:
                        waveform_freq.push(Math.round(getOutputValue(start_freq + (end_freq - start_freq) * (Math.floor(m / (duration / waveinfo[i + 1].length)) / waveinfo[i + 1].length))))
                        break
                }
            }
        }
        /** 单小节频率和强度数据合并 */
        for (let i = 0; i < waveform_freq.length; i += 4) {
            waveform.push([[waveform_freq[i], waveform_freq[i + 1], waveform_freq[i + 2], waveform_freq[i + 3]], [waveform_strength[i], waveform_strength[i + 1], waveform_strength[i + 2], waveform_strength[i + 3]]])
        }
    }
    return waveform
}
async function 二维码解析(e) {
    let image = e.message.filter(i => i.type === 'image');
    const 检测转发 = async (messages) => {
        for (const item of messages) {
            if (item.type === 'json') {
                const forwards = await getMessage(item);
                forwards.forEach(forwardItem => {
                    if (forwardItem.type === 'image') {
                        image.push(forwardItem);
                    }
                });
            }
        }
    };
    if (e.source && e.source.seq) {
        let history = await e.group.getChatHistory(e.source.seq, 1);
        let messages = history?.pop()?.message || [];
        await 检测转发(messages);
        messages.forEach(i => {
            if (i.type === 'image') {
                image.push(i);
            }
        });
    } else if (e.source) {
        logger.error('未提取到source.seq,无法提取回复的消息');
    }
    await 检测转发(e.message);
    image = image.map(i => i.url).filter(Boolean);
    if (image.length === 0) {
        await e.reply('未提取到图片');
        return false;
    }
    const Items = await Promise.all(
        image.map(async (url, index) => ({
            url: await 读取二维码(url),
            index,
        }))
    );
    Items.sort((a, b) => a.index - b.index);
    return Items.map(i => i.url);
}

async function getMessage(item) {
    let msgs = [];
    const data = parseData(item.data);
    const resid = item.type == 'json' && data?.meta?.detail?.resid ? data.meta.detail.resid : null;
    if (resid) {
        const res = await Bot.getForwardMsg(resid);
        if (res) {
            for (const i of res) {
                for (const ii of i.message) {
                    const nestedData = parseData(ii.data);
                    const nestedResid = ii.type == 'json' && nestedData?.meta?.detail?.resid ? nestedData.meta.detail.resid : null;
                    if (nestedResid) {
                        const nestedMsgs = await getMessage(ii);
                        msgs = msgs.concat(nestedMsgs);
                    } else {
                        msgs.push(ii);
                    }
                }
            }
        }
    } else {
        msgs.push(item);
    }
    return msgs;
}
async function 读取二维码(url) {
    try {
        const image = await Jimp.read(url);
        const { data, width, height } = image.bitmap;
        const qrCode = jsQR(data, width, height);
        if (qrCode) {
            return qrCode.data;
        } else {
            return null;
        }
    } catch (err) {
        logger.error('二维码读取失败:', err);
        return null;
    }
}
function parseData(data) {
    try {
        return JSON.parse(data);
    } catch (err) {
        return null;
    }
}